class Promise {
	// static PENDING = 'PENDING'
	// static FUFILLED = 'FUFILLED'
	// static REJECTED = 'REJECTED'
	constructor (executor) {
		// 检验用户传过来的executor是不是函数
		if (typeof executor !== 'function') {
			throw new TypeError(`Promise resolver ${executor} is not a function`)
		}

		this.initValue() // 执行初始值
		this.initBind() // 绑定 resolve和reject的this指向

		try {
			// 执行用户传递过来的executor函数，并将resolve和reject函数当参数传递回去
			executor(this.resolve, this.reject)
		} catch (e) {
			this.reject(e)
		}
	}

	// 绑定this
	initBind () {
		// 绑定的原因是： 在将resolve、reject函数作为executor函数参数传递回去的时候
		// 用户会 resolve() 或 reject() 调用函数，这样在严格模式下this指向undefined
		this.resolve = this.resolve.bind(this)
		this.reject = this.reject.bind(this)
	}
	// 初始值
	initValue () {
		this.value = null // 终值
		this.reason = null // 拒因
		this.state = Promise.PENDING // pending fulfilled rejected
		this.onFulfilledCallbacks = []
		this.onRejectedCallbacks = []
	}

	resolve (value) {
		// 成功之后一系列操作 （状态的改变，成功回调的执行）
		if (this.state === Promise.PENDING) {
			this.state = Promise.FUFILLED
			this.value = value
			this.onFulfilledCallbacks.forEach(fn => fn(value) )
		}
	}

	reject (reason) {
		// 失败之后一系列操作 （状态的改变，失败回调的执行）
		if (this.state === Promise.PENDING) {
			this.state = Promise.REJECTED
			this.reason = reason
			this.onRejectedCallbacks.forEach(fn => fn(reason) )
		}
	}

	

	then (onFulfilled, onRejected) {
		// 调用then方法时执行 下面语句
		// 判断传递的两个参数是不是函数
		if (typeof onFulfilled !== 'function') {
			onFulfilled = function (value) {
				return value
			}
		}

		if (typeof onRejected !== 'function') {
			onRejected = function (reason) {
				throw reason
			}
		}
		const promise2 = new Promise((resolve, reject) => {
			
			// 当状态为 fulfilled 时才执行 onFulfilled
			if (this.state === Promise.FUFILLED) {
				setTimeout(() => { // 加上setTimeout的原因，是利用了事件循环的特性，让onFulfilled函数在所有的宏任务执行完之后再执行
					try {
						const x = onFulfilled(this.value)
						// resolve(x)
						Promise.resolvePromise(promise2, x, resolve, reject)
					} catch (e) {
						reject(e)
					}
				})
			}

			// 当状态为 rejected 时才执行 onRejected
			if (this.state === Promise.REJECTED) {
				setTimeout(() => { // 加上setTimeout的原因，是利用了事件循环的特性，让onRejected函数在所有的宏任务执行完之后再执行
					try {
						const x = onRejected(this.reason)
						// resolve(x)
						Promise.resolvePromise(promise2, x, resolve, reject)
					} catch (e) {
						reject(e)
					}
				})
			}


			// 这种情况是executor函数中，执行了异步方法，在异步方法内部调用了resolve、reject，这就会导致执行then方法是this.state一直都是padding
			if (this.state === Promise.PENDING) {
				// 我们需要将要执行的onFulfilled和onRejected方法，放进数组中
				this.onFulfilledCallbacks.push((value) => {
					setTimeout(() => {
						try {
							const x = onFulfilled(value)
							// resolve(x)
							Promise.resolvePromise(promise2, x, resolve, reject)
						} catch (e) {
							reject(e)
						}
					})
				})

				this.onRejectedCallbacks.push((reason) => {
					setTimeout(() => {
						try {
							const x = onRejected(this.reason)
							// resolve(x)
							Promise.resolvePromise(promise2, x, resolve, reject)
						} catch (e) {
							reject(e)
						}
					})
				})
			}

			
		})

		return promise2
	}
}
Promise.PENDING = 'pending'
Promise.FUFILLED = 'fulfilled'
Promise.REJECTED = 'reject'
Promise.resolvePromise = function(promise2, x, resolve, reject) {
	if (promise2 === x) { 
		//  返回的Promise对象是自身的话，报循环调用错误
		reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
	}

	let called = false // 未被调用

	if (x instanceof Promise) {
		// 判断x返回值是否是Promise对象，那么需要等待Promise对象执行完成，将相同结果或拒绝原因，执行或拒绝Promise
		x.then(res => {
			Promise.resolvePromise(promise2, res, resolve, reject) // 这里有可能返回的还是Promise,所以需要继续执行Promise.resolvePromise
			// resolve(res)
		}, reason => {
			reject(reason)
		})
	} else if (x !== null && (typeof x === 'object' || typeof x === 'function')){
		// 判断x是否是对象或者函数，且不为null ; 判断x是否有then方法,，有的话执行，将结果resolve回去，否则直接resolve(x)
		// 注意调用x.then有可能会出现异常；因为x.then方法有可能设置了属性的描述属性，出现异常，所以要捕获一下
		try { 
			const then = x.then
			if (typeof then === 'function') {
					then.call(x, value => {
						if (called) return
						called = true
						Promise.resolvePromise(promise2, value, resolve, reject)
					}, reason => {
						if (called) return
						called = true
						reject(reason)
					})
				
			} else {
				if (called) return
				called = true
				resolve(x)
			}
		} catch (e) {
			if (called) return
			called = true
			reject(e)
		}

	} else {
		resolve(x)
	}
}
Promise.resolve = function(value){
	return new Promise(resolve => {
		resolve(value)
	})
}
Promise.reject = function(reason){
	return new Promise((resolve, reject) => {
		reject(reason)
	})
}
/*
all 方法，当所有的都promise都执行完，且没有 拒绝reject，按顺序返回结果数组
如果有一个出错，那么就调用reject方法，并将拒因返回
 */
Promise.all = function(promises){
	const values = []
	return new Promise((resolve, reject) => {
		promises.forEach(promise => {
			promise.then(value => {
				values.push(value)
				if (values.length === promises.length) {
					resolve(values)
				}
			}, reason => {
				reject(reason)
			})
		})
	})
}
Promise.race = function (promises) {
	 return new Promise((resolve, reject) => {
		promises.forEach(promise => {
			promise.then(value => {
				resolve(value) // 执行成功
			}, reason => {
				reject(reason) // 执行拒绝
			})
		})
	})
}
// Promise.defer = Promise.deferred = function() {
//   let dfd = {}
//   dfd.promise = new Promise((resolve, reject) => {
//     dfd.resolve = resolve
//     dfd.reject = reject
//   })
//   return dfd
// }
// module.exports = Promise
/*
这里加setTimeout的原因是： 让下面的输出为 1  2  3  4 

if (this.state === Promise.FUFILLED) {
	setTimeout(() => { // 加上setTimeout的原因，是利用了事件循环的特性，让onFulfilled函数在所有的宏任务执行完之后再执行
		onFulfilled(this.value)
	})
}

// 当状态为 rejected 时才执行 onRejected
if (this.state === Promise.REJECTED) {
	setTimeout(() => { // 加上setTimeout的原因，是利用了事件循环的特性，让onRejected函数在所有的宏任务执行完之后再执行
		onRejected(this.reason)
	})
}


console.log('1')
const Promise = new Promise((resolve, reject) => {
	console.log('2')
	resolve(1)
})
.then(res => {
	console.log('4')
	console.log('res', res)
}, reason => {
	console.log('reason', reason)
})
console.log('3')
 */


/*
console.log('1')
const Promise = new Promise((resolve, reject) => {
	console.log('2')
	setTimeout(()=>{
		console.log('4')
		resolve(1)
	})
})
.then(res => {
	console.log('5')
	console.log('res', res)
}, reason => {
	console.log('reason', reason)
})
console.log('3')

这种情况下需要输出 1  2  3 4 5

这种情况是executor函数中，执行了异步方法，在异步方法内部调用了resolve、reject，这就会导致执行then方法是this.state一直都是padding
所以then中的不会执行回调，函数；
我们既要解决在padding状态下执行回调函数，还要在executor函数执行后输出：
方案：在then函数中，判断状态为padding时，将要执行的 onFulfilled, onRejected函数存在数组中缓存起来，等executor函数执行之后，在对应的
resolve, reject函数中执行数组中缓存的函数即可
 */


/*
then 链式调用的说明
由于 promise的状态是不可以逆的，所以实现链式调用，就必须返回一个新的promise实例，
我们在上一个promise的then中的onFulfilled, onRejected函数中的返回值，都认为返回的是resolve结果，所以我们获取到onFulfilled, onRejected函数返回结果，
并在新Promise中使用resolve(结果)，即可完成链式的调用


 */

 /*
then 返回值说明

可以是 一个 Promise对象
const p1 =  new Promise(resolve => resolve(1))
const p2 =  new Promise(resolve => resolve(2))
	.then(res => {
		console.log('p2', res)  // p2  2
		return p1
	})
	.then(res => {
		console.log('p1', res)  // p1  1
	})
但是，返回的Promise对象不能是调用者不能是自己本身，要不然报循环调用错误  Chaining cycle detected for promise #<Promise>
const p2 =  new Promise(resolve => resolve(2))
	.then(res => {
		return p2  // 报错： Chaining cycle detected for promise #<Promise>
	})



2、 返回的Promose的对象中，有可能还返回Promise对象，所以我们需要继续等Promise执行完之后再进行输出值
const Promise = new Promise((resolve, reject) => {
			resolve(1)
		}).then(res => {
			console.log(res)
			return new Promise((resolve, reject) => {
				resolve(
					new Promise((resolve, reject) => {resolve(100)})
				)
			})
		}, error=> {
			console.log(error)
		})
		.then(res => {
			console.log(res)
		}, error=> {
			console.log(error)
		})
解决：
if (x instanceof Promise) {
	// 判断x返回值是否是Promise对象，那么需要等待Promise对象执行完成，将相同结果或拒绝原因，执行或拒绝Promise
	x.then(res => {
		Promise.resolvePromise(promise2, res, resolve, reject) // 这里有可能返回的还是Promise,所以需要继续执行Promise.resolvePromise
		// resolve(res)
	}, reason => {
		rejecte(reason)
	})
}


可以是一个基本类型的值

注意： 若resolvePromise和rejectPromise均被调用，或被同一参数都多用多次，则优先采用首次调用，并忽略后面剩下的调用
所以我们定义called变量，来标明是否已经被调用了

 */